package com.ljf.order.service.impl;

import com.example.demo.client.ProductClient;
import com.example.demo.dataobject.ProductInfoOutput;
import com.example.demo.dto.DecreaseStockInput;
import com.ljf.order.dataobject.OrderDetail;
import com.ljf.order.dataobject.OrderMaster;
import com.ljf.order.dto.CartDTO;
import com.ljf.order.dto.OrderDTO;
import com.ljf.order.enums.OrderStatusEnum;
import com.ljf.order.enums.PayStatusEnum;
import com.ljf.order.enums.ResultEnum;
import com.ljf.order.exception.SellException;
import com.ljf.order.respository.OrderDetailRepository;
import com.ljf.order.respository.OrderMasterRepository;
import com.ljf.order.service.OrderService;
import com.ljf.order.util.BeanCopy;
import com.ljf.order.util.PrimaryKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: Ljf
 * @Date : 2019/1/31 23:58
 * @Description :
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private ProductClient productClient;
    @Autowired
    private OrderDetailRepository orderDetailRepository;
    @Autowired
    private OrderMasterRepository orderMasterRepository;

    @Override
    @Transactional
    public OrderDTO create(OrderDTO orderDTO) {
        //查询商品 （数量，价格）
        String orderId = PrimaryKeyUtil.genUniqueKey();
        List<String> productIds = orderDTO.getOrderDetails().stream().map(OrderDetail::getProductId).collect(Collectors.toList());
        List<ProductInfoOutput> productInfoOutputs = productClient.listForOrder(productIds);
        //计算总价
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);
        for (OrderDetail orderDetail : orderDTO.getOrderDetails()) {
            for (ProductInfoOutput one : productInfoOutputs) {
                if (one == null) {
                    throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
                }
                orderAmount = one.getProductPrice().multiply
                        (new BigDecimal(orderDetail.getProductQuantity())).add(orderAmount);
                orderDetail.setOrderId(orderId);
                orderDetail.setDetailId(PrimaryKeyUtil.genUniqueKey());
                BeanUtils.copyProperties(one, orderDetail, OrderDetail.class);
                orderDetailRepository.save(orderDetail);
            }
        }
        //写入订单数据库
        OrderMaster master = new OrderMaster();
        BeanUtils.copyProperties(orderDTO, master, OrderMaster.class);
        master.setOrderId(orderId);
        master.setOrderAmount(orderAmount);
        master.setOrderStatus(0);
        master.setPayStatus(0);
        orderMasterRepository.save(master);
        //扣库存
        List<DecreaseStockInput> collect = orderDTO.getOrderDetails().stream().map
                (e -> new DecreaseStockInput(e.getProductId(), e.getProductQuantity()))
                .collect(Collectors.toList());
        productClient.decreaseStock(collect);
        BeanUtils.copyProperties(master, orderDTO, OrderDTO.class);
        return orderDTO;
    }

    @Override
    public OrderDTO findOne(String orderId) {
        OrderDTO dto = new OrderDTO();
        OrderMaster one = orderMasterRepository.getOne(orderId);
        if (one != null) {
            BeanCopy.copyProperties(one, dto, OrderDTO.class);
            List<OrderDetail> orderDetails = orderDetailRepository.findByOrderId(orderId);
            if (CollectionUtils.isEmpty(orderDetails)) {
                throw new SellException(ResultEnum.ORDER_NOT_EXIST);
            }
            dto.setOrderDetails(orderDetails);
        } else {
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }
        return dto;
    }

    @Override
    public Page<OrderDTO> findList(String buyerOpenid, Pageable pageable) {
        Page<OrderMaster> page = orderMasterRepository.findByBuyerOpenid(buyerOpenid, pageable);
        List<OrderDTO> dtos = new ArrayList<>();
        BeanCopy.copyPropertiesForListWithBlank2Null(page.getContent(), dtos, OrderDTO.class);
        return new PageImpl<OrderDTO>(dtos, pageable, page.getTotalElements());
    }

    @Override
    @Transactional
    public OrderDTO cancel(OrderDTO orderDTO) {
        if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【取消订单】 订单状态不正确,orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        OrderMaster master = new OrderMaster();
        BeanCopy.copyProperties(orderDTO, master, OrderMaster.class);
        master.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
        OrderMaster updateResult = orderMasterRepository.save(master);
        BeanCopy.copyProperties(updateResult, orderDTO, OrderDTO.class);
        if (updateResult == null) {
            log.error("【取消订单】 更新失败,orderMaster={}", master);
            throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
        }
        List<CartDTO> collect = orderDTO.getOrderDetails().stream().
                map(e -> new CartDTO(e.getProductId(), e.getProductQuantity())).
                collect(Collectors.toList());
       // productClient.increaseStock(collect);
        //如果已支付，则需要退款  TODO
        return orderDTO;
    }

    //都没回答棉袜每次
    @Override
    public OrderDTO finish(OrderDTO orderDTO) {
        if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【订单完成】 订单状态不正确,orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //修改支付状态
        if (!orderDTO.getPayStatus().equals(PayStatusEnum.WAIT.getCode())) {
            log.error("【订单支付完成】 订单支付状态不正确,orderDTO={}", orderDTO);
            throw new SellException(ResultEnum.ORDER_PAYSTATUS_ERROR);
        }
        //修改订单状态
        orderDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
        OrderMaster master = new OrderMaster();
        BeanCopy.copyProperties(orderDTO, master, OrderMaster.class);
        OrderMaster save = orderMasterRepository.save(master);
        if (save == null) {
            log.error("【完结订单】  更新失败,oderMater={}", master);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }
        return orderDTO;
    }

    @Override
    @Transactional
    public OrderDTO paid(OrderDTO orderDTO) {
        if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【取消订单】 订单状态不正确,orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //修改支付状态
        if (!orderDTO.getPayStatus().equals(PayStatusEnum.WAIT.getCode())) {
            log.error("【订单支付完成】 订单支付状态不正确,orderDTO={}", orderDTO);
            throw new SellException(ResultEnum.ORDER_PAYSTATUS_ERROR);
        }
        //修改支付状态
        orderDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        OrderMaster master = new OrderMaster();
        BeanCopy.copyProperties(orderDTO, master, OrderMaster.class);
        OrderMaster save = orderMasterRepository.save(master);
        if (save == null) {
            log.error("【完结订单】  更新失败,oderMater={}", master);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }
        return orderDTO;
    }
}
